/**
 * 文件名：****.java
 * 版权：Copyright Lightkit All Rights Reserved.
 * 描述：*****
 */
package com.lightkits.wms.domain.stocktransfer.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.lightkits.common.db.entity.BdTransaction;
import com.lightkits.common.db.entity.FndTransactionTypeBase;
import com.lightkits.common.db.entity.FndWmMoveTypeBase;
import com.lightkits.common.db.entity.FndWorker;
import com.lightkits.common.service.CommonTransactionService;
import com.lightkits.framework.common.exception.LightKitsBizException;
import com.lightkits.framework.common.model.CheckResult;
import com.lightkits.framework.common.model.IResult;
import com.lightkits.framework.common.utility.object.ObjectUtil;
import com.lightkits.framework.common.utility.object.ParseUtil;
import com.lightkits.framework.common.utility.validate.IntegrityValidator;
import com.lightkits.framework.soa.client.id.GetGlobalIDRequestType;
import com.lightkits.framework.soa.client.id.GetGlobalIDResponseType;
import com.lightkits.framework.soa.client.id.IDServiceClient;
import com.lightkits.wms.domain.saveonhand.models.OnhandParams;
import com.lightkits.wms.domain.saveonhand.service.UseParamsDomain;
import com.lightkits.wms.domain.stocktransfer.service.OrgSubStockTransDomain;
import com.lightkits.wms.dto.onhand.model.OnhandDTO;
import com.lightkits.wms.dto.stocktransfer.model.OrgSubStockViewDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * @author jing.wei@hand-china.com
 * @date 2019/5/28 10:20
 **/
@Service
public class OrgSubStockTransDomainImpl implements OrgSubStockTransDomain {

    private final IDServiceClient idServiceClient;
    private final CommonTransactionService service;
    private final UseParamsDomain useParamsDomain;

    @Autowired
    public OrgSubStockTransDomainImpl(IDServiceClient idServiceClient,
                                      CommonTransactionService service,
                                      UseParamsDomain useParamsDomain) {
        this.idServiceClient = idServiceClient;
        this.service = service;
        this.useParamsDomain = useParamsDomain;
    }

    /**
     * @param viewDto 组织间转移参数
     * @return IResult
     * 组织间转移参数校验
     **/
    private IResult checkParams(OrgSubStockViewDto viewDto) {

        try {
            IntegrityValidator.begin()
                    .validate(viewDto.getEventRequestId(), "Event Request Id")
                    .validate(viewDto.getOutOrgId(), "Out Organization Id")
                    .validate(viewDto.getInOrgId(), "In Organization Id")
                    .validate(viewDto.getUomCode(), "Uom")
                    .validate(viewDto.getItemId(), "Item Id")
                    .validate(viewDto.getOutWarehouseId(), "Out Warehouse Id")
                    .validate(viewDto.getOwnerType(), "Owner Type")
                    .validate(viewDto.getInWarehouseId(), "In Warehouse Id")
                    .validate(viewDto.getMoveTypeCode(), "Move Type Code")
                    .validate(viewDto.getTransferQty(), "Transfer Quantity");
        } catch (LightKitsBizException e) {
            return e.result();
        }
        return IResult.success();
    }

    /**
     * @param stockViewDTO 组织间库存转移参数
     * @param direaction   转移方向
     * @return 现有量参数
     **/
    private CheckResult<OnhandDTO> convertParams(OrgSubStockViewDto stockViewDTO,
                                                 String direaction) {
        CheckResult<OnhandDTO> checkResult = new CheckResult<>();
        checkResult.setSuccessful(true);
        OnhandDTO params = new OnhandDTO();
        if (ObjectUtil.isNullOrEmpty(direaction)) {
            checkResult.setSuccessful(false);
            checkResult.setMessage("the direction is null");
            return checkResult;
        }
        if (!direaction.equals("OUT") && !direaction.equals("IN") && !direaction.equals("ALL")) {
            checkResult.setSuccessful(false);
            checkResult.setMessage("the direction in undefiend");
            return checkResult;
        }
            params.setEventRequestId(ParseUtil.tryLongWithException(stockViewDTO.getEventRequestId()));
            params.setWorkerId(stockViewDTO.getWorkerId());
            params.setParentEventId(stockViewDTO.getParentEventId());
            params.setItemId(stockViewDTO.getItemId());
            params.setUomCode(stockViewDTO.getUomCode());
            params.setOwnerType(stockViewDTO.getOwnerType());
            params.setOwnerId(stockViewDTO.getOwnerId());
            params.setLotNumber(stockViewDTO.getLot());
            params.setRemark(stockViewDTO.getRemark());
            params.setChangeQuantity(stockViewDTO.getTransferQty());
            if (direaction.equals("OUT")) {
                params.setEventTypeCode("WM_MTL_TRANS_OUT");
                params.setWarehouseId(stockViewDTO.getOutWarehouseId());
                params.setOrgId(stockViewDTO.getOutOrgId());
                params.setWmAreaId(stockViewDTO.getOutWmAreaId());
                params.setChangeDirection("OUT");
            }
            if (direaction.equals("IN")) {
                params.setEventTypeCode("WM_MTL_TRANS_IN");
                params.setWarehouseId(stockViewDTO.getInWarehouseId());
                params.setWmAreaId(stockViewDTO.getInWmAreaId());
                params.setOrgId(stockViewDTO.getInOrgId());
                params.setChangeDirection("IN");
            }

            checkResult.setData(params);
        return checkResult;
    }

    /**
     * @param stockViewDTO 组织间转移参数
     * @param direaction   转移方向
     * @param transTypeId  事务类型ID
     * @param moveTypeId   移动类型ID
     * @return BdTransaction 事务参数
     **/
    private BdTransaction createTranscation(OrgSubStockViewDto stockViewDTO,
                                            String direaction,
                                            Long transTypeId,
                                            Long moveTypeId) {
        BdTransaction trans = new BdTransaction();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

        GetGlobalIDRequestType idRequest = new GetGlobalIDRequestType();
        idRequest.setCount(1);
        GetGlobalIDResponseType idResponse = idServiceClient.getGlobalId(idRequest);
        Iterator<Long> sfIds = idResponse.getIds().iterator();
        FndTransactionTypeBase base = new FndTransactionTypeBase()
                .selectById(transTypeId);
        trans.setTransactionTypeId(transTypeId);
        trans.setTransactionTypeCode(base.getTransactionTypeCode());
        trans.setId(sfIds.next());
        trans.setItemId(ParseUtil.tryLongWithException(stockViewDTO.getItemId()));
        trans.setTransactionUom(stockViewDTO.getUomCode());
        trans.setTransactionDate(new Date());
        if (!ObjectUtil.isNullOrEmpty(stockViewDTO.getDocumentTypeId())) {
            trans.setDocumentTypeId(ParseUtil.tryLongWithException(stockViewDTO.getDocumentTypeId()));
        }
        if (!ObjectUtil.isNullOrEmpty(stockViewDTO.getDocumentLineId())) {
            trans.setDocumentLineId(ParseUtil.tryLongWithException(stockViewDTO.getDocumentLineId()));
        }
        if (!ObjectUtil.isNullOrEmpty(stockViewDTO.getDocumentId())) {
            trans.setDocumentId(ParseUtil.tryLongWithException(stockViewDTO.getDocumentId()));
        }
        trans.setDocumentTypeCode(stockViewDTO.getDocumentTypeCode());
        trans.setDocumentNum(stockViewDTO.getDocumentNum());
        trans.setLotNumber(stockViewDTO.getLot());
        format.applyPattern("HH:mm:ss");
        trans.setTransactionTime(new Date());
        if (direaction.equals("OUT")) {
            trans.setOrganizationId(ParseUtil.tryLongWithException(stockViewDTO.getOutOrgId()));
            trans.setTransactionQty(new BigDecimal(stockViewDTO.getTransferQty()));
            trans.setWarehouseId(ParseUtil.tryLongWithException(stockViewDTO.getOutWarehouseId()));
            if (!ObjectUtil.isNullOrEmpty(stockViewDTO.getOutWmAreaId())) {
                trans.setWmAreaId(ParseUtil.tryLongWithException(stockViewDTO.getOutWmAreaId()));
            }
        }
        if (direaction.equals("IN")) {
            trans.setTransactionQty(new BigDecimal(stockViewDTO.getTransferQty()).negate());
            trans.setOrganizationId(ParseUtil.tryLongWithException(stockViewDTO.getInOrgId()));
            trans.setWarehouseId(ParseUtil.tryLongWithException(stockViewDTO.getInWarehouseId()));
            if (!ObjectUtil.isNullOrEmpty(stockViewDTO.getInWmAreaId())) {
                trans.setWmAreaId(ParseUtil.tryLongWithException(stockViewDTO.getInWmAreaId()));
            }
        }
        trans.setWorkerId(ParseUtil.tryLongWithException(stockViewDTO.getWorkerId()));
        trans.setEventRequestId(ParseUtil.tryLongWithException(stockViewDTO.getEventRequestId()));
        FndWorker worker = new FndWorker().selectById(stockViewDTO.getWorkerId());
        trans.setWorkerNumber(worker.getWorkerNumber());
        trans.setTransactionReasonCode(moveTypeId);
        trans.setRemark(stockViewDTO.getRemark());
        return trans;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public IResult orgSubStockTrans(OrgSubStockViewDto viewDTO) {
        if (ObjectUtil.isNullOrEmpty(viewDTO.getEventRequestId())) {
            GetGlobalIDRequestType idRequest = new GetGlobalIDRequestType();
            idRequest.setCount(1);
            GetGlobalIDResponseType idResponse = idServiceClient.getGlobalId(idRequest);
            Iterator<Long> sfIds = idResponse.getIds().iterator();
            viewDTO.setEventRequestId(sfIds.next().toString());
        }

        IResult result = null;
        result = this.checkParams(viewDTO);
        if (!result.isSuccessful()) {
            return result;
        }
        CheckResult<OnhandDTO> outOnhandParams = convertParams(viewDTO, "OUT");
        CheckResult<OnhandDTO> inOnhandParams = convertParams(viewDTO, "IN");
        if (!outOnhandParams.isSuccessful()) {
            return IResult.fail(outOnhandParams.getMessage());
        }
        if (!inOnhandParams.isSuccessful()) {
            return IResult.fail(inOnhandParams.getMessage());
        }
        CheckResult<OnhandParams> checkResultRes = useParamsDomain.getOnhandParams(outOnhandParams.getData());
        if (!checkResultRes.isSuccessful() || checkResultRes.getData() == null) {
            throw new LightKitsBizException(checkResultRes.getMessage());
        }
        CheckResult resultOut = useParamsDomain.insertValue(checkResultRes.getData());
        if (!resultOut.isSuccessful()) {
            throw new LightKitsBizException(resultOut.getMessage());
        }
        checkResultRes = useParamsDomain.getOnhandParams(inOnhandParams.getData());
        if (!checkResultRes.isSuccessful() || checkResultRes.getData() == null) {
            throw new LightKitsBizException(checkResultRes.getMessage());
        }
        CheckResult resultIn = useParamsDomain.insertValue(checkResultRes.getData());
        if (!resultIn.isSuccessful()) {
            throw new LightKitsBizException(resultIn.getMessage());
        }
        FndWmMoveTypeBase moveTypeBase = new FndWmMoveTypeBase()
                .selectOne(new EntityWrapper()
                        .eq(FndWmMoveTypeBase.MOVE_TYPE_CODE, viewDTO.getMoveTypeCode()));
        if (!ObjectUtil.isEmpty(moveTypeBase.getTransactionTypeId())) {
            //create transcation
            List<BdTransaction> transactions = new ArrayList<>();
            BdTransaction positiveTrans = createTranscation(
                    viewDTO, "OUT", moveTypeBase.getTransactionTypeId(), moveTypeBase.getId());
            BdTransaction reverseTrans = createTranscation(
                    viewDTO, "IN", moveTypeBase.getTransactionTypeId(), moveTypeBase.getId());
            positiveTrans.setParentTransactionId(reverseTrans.getId());
            reverseTrans.setParentTransactionId(positiveTrans.getId());
            transactions.add(positiveTrans);
            transactions.add(reverseTrans);
            service.saveTransaction(transactions);
        }

        return result;

    }


}
